#include <random>
#include <cassert>
#include "../include/Game.hpp"

bool Game::Initialize(const std::string &build_path)
{
    bool success = false;
    InitAudioDevice();                                                  // 初始化音频设备和上下文
    music = LoadMusicStream((build_path + "sounds/music.mp3").c_str()); // 从文件加载音乐流
    // ctxData非空通常意味着音乐文件成功加载并初始化。
    if (music.ctxData) // 音频的上下文数据，void*
    {
        PlayMusicStream(music);                                              // 开始播放音乐
        rotateSound = LoadSound((build_path + "sounds/rotate.mp3").c_str()); // 从文件加载音频
        // 这行代码断言rotateSound对象中的frameCount成员大于0，这意味着音效文件成功加载并包含至少一帧音频数据
        if (rotateSound.frameCount > 0)
        {
            clearSound = LoadSound((build_path + "sounds/clear.mp3").c_str());
            if (clearSound.frameCount > 0)
            {
                success = true;
            }
            else
            {
                UnloadMusicStream(music); // 卸载音乐流
                UnloadSound(rotateSound); // 卸载音频
            }
        }
        else
        {
            UnloadMusicStream(music);
        }
    }

    return success;
}

Game::Game()
    :currentBlock(GetRandomBlock())
    ,nextBlock(GetRandomBlock())
    ,music()
    ,rotateSound()
    ,clearSound()
    ,grid()
    ,score(0)
{}

Game::~Game()
{
    UnloadMusicStream(music); // 卸载音乐流
    UnloadSound(rotateSound); // 卸载音频
    UnloadSound(clearSound);
}

void Game::Draw()
{
    grid.Draw();
    currentBlock.draw(11,11);
    switch(nextBlock.GetId())
    {
    case 2:
        nextBlock.draw(260,290);//保证在x，270，y，270画出，即在圆角矩形中，因为还要加上blocks.hpp的move() * _cellsize，即360
        break;
    case 3:
        nextBlock.draw(290,250);
        break;
    default:
        nextBlock.draw(270,270);
        break;
    }
}

void Game::HandleInput()
{
    int KeyPress = GetKeyPressed();//按下按键(keycode), 对排队的按键多次调用, 当队列为空时返回0
    if(GameOver && KeyPress > 0)//游戏结束，并且检测到按下任何按键，重新开始游戏
    {
        GameOver = false;
        reset();
    }
    switch(KeyPress)//处理各自按键请求
    {
    case KEY_LEFT:
        MoveBlockLeft();
        break;
    case KEY_RIGHT:
        MoveBlockRight();
        break;
    case KEY_UP:
        RotateBlock();
        break;
    case KEY_DOWN:
        MoveBlockDown();
        UpdateScore(0,1);//因为加速下落，所以增加分数
        break;
    default:
        break;
    }
}

void Game::MoveBlockLeft()
{
    if(!GameOver)
    {
        currentBlock.move(0,-1);
        if(IsOutGridSize() || BlockFits())//超出边界或者重叠，不处理
        {
            currentBlock.move(0,1);
        }
    }   
}

void Game::MoveBlockRight()
{
    if(!GameOver)
    {
        currentBlock.move(0,1);
        if(IsOutGridSize() || BlockFits())//超出边界或者重叠，不处理
        {
            currentBlock.move(0,-1);
        }
    }
}

void Game::MoveBlockDown()
{
    if(!GameOver)
    {
        currentBlock.move(1,0);
        if(IsOutGridSize() || BlockFits())//超出边界或者重叠，不处理
        {
            currentBlock.move(-1,0);//因为当前方块已经不能继续向下走了，锁定方块
            LockBlock();
        }
    }
}

void Game::RotateBlock()
{
    if(!GameOver)
    {
        currentBlock.rotate();
        if(IsOutGridSize() || BlockFits())//超出边界或者重叠，不处理
        {
            currentBlock.UndoRotate();
        }
        else
        {
            PlaySound(rotateSound);
        }
    }
}

void Game::LockBlock()
{
    std::vector<Position> tiles = currentBlock.GetBlockPosition();
    for(const Position& pos : tiles)//将方块锁定后的位置，更新到棋盘内
    {
        grid.grid(pos._row,pos._col) = currentBlock.GetId();
    }
    currentBlock = nextBlock;//更新方块
    if(BlockFits())//下一个方块刚出来就重叠，证明游戏结束了
    {
        GameOver = true;
    }
    nextBlock = GetRandomBlock();
    int ClearNum = grid.ClearAllRow();//清理
    if(ClearNum > 0)
    {
        PlaySound(clearSound);//播放清理的音乐
        UpdateScore(ClearNum,0);//更新分数
    }
}

const std::vector<Block>& Game::GetAllBlocks()
{
    static std::vector<Block> AllBlocks = {JBlock(),OBlock(),IBlock(),SBlock(),ZBlock(),LBlock(),TBlock()};
    return AllBlocks;
}

void Game::UpdateScore(unsigned int LinesClear,unsigned int DownPoints)
{
    if(LinesClear > 0)
    {
        switch (LinesClear)
        {
        case 1:
            score += 100;
            break;
        case 2:
            score += 300;
            break;
        case 3:
            score += 500;
            break;
        default:
            score += 800;
            break;
        }
    }
    score += DownPoints;
}

bool Game::IsOutGridSize()
{
    std::vector<Position> tiles = currentBlock.GetBlockPosition();
    for(const Position& pos : tiles)
    {
        if(grid.IsOutRange(pos._row,pos._col))//是否超出边界
        {
            return true;
        }
    }

    return false;
}

bool Game::BlockFits()
{
    std::vector<Position> tiles = currentBlock.GetBlockPosition();
    for(const Position& pos : tiles)
    {
        if(!grid.PosIsEmpty(pos._row,pos._col))//有一个不为空，重叠
        {
            return true;
        }
    }

    return false;
}

const Block& Game::GetRandomBlock()
{
    const std::vector<Block>& AllBlocks(GetAllBlocks());
    std::random_device rd;//创建随机数种子
    std::mt19937 gen(rd());//使用Mersenne Twister引擎，它是一个高质量的伪随机数生成器  
    std::uniform_int_distribution<> dis(0,(int)AllBlocks.size() - 1);//随机数范围
    return AllBlocks[dis(gen)];
}

void Game::reset()
{
    grid.initialize();//清理所有的矩形
    currentBlock = GetRandomBlock();
    nextBlock = GetRandomBlock();
    score = 0;
}

